package com.hl.toolkit.pay.controller;

import com.tycoin.account.slaveentity.TycoinAccountRecharge;
import com.tycoin.account.slaveservice.TycoinAccountRechargeCallbackProcessService;
import com.tycoin.account.slaveservice.TycoinAccountRechargeService;
import com.tycoin.user.slaveentity.TycoinUser;
import com.tycoin.user.slaveservice.TycoinUserService;
import com.unionpay.acp.demo.Form_6_4_Refund;
import com.unionpay.acp.demo.Form_6_5_Query;
import com.unionpay.acp.demo.consume.Form_6_2_FrontConsume;
import com.unionpay.acp.sdk.AcpService;
import com.unionpay.acp.sdk.LogUtil;
import com.unionpay.acp.sdk.SDKConstants;
import com.util.HttpClientUtils;
import com.util.RandomUtils;
import com.util.StringUtil;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 银联支付
 */
@Controller
@RequestMapping(value = { "/interface/UnionPay" })
public class UnionpayController extends AbstractController {

	@Autowired
	private TycoinAccountRechargeService tycoinAccountRechargeService;
	@Autowired
	private TycoinAccountRechargeCallbackProcessService tycoinAccountRechargeCallbackProcessService;

	@Autowired
	private TycoinUserService tycoinUserService;

	@RequestMapping(value = "/WapPay")
	public void WapPay(HttpServletRequest request, HttpServletResponse reponse) throws IOException {
		PrintWriter out = reponse.getWriter();
		String txnAmt = request.getParameter("txnAmt");
		String userId = request.getParameter("userId");
		String frontUrl = request.getParameter("frontUrl");
		String unionNotifUrl = request.getParameter("unionNotifUrl");

		long dateTime = System.currentTimeMillis();
		String outTradeNo = "union" + String.valueOf(dateTime) + String.valueOf((long) (Math.random() * 100000L));

		TycoinAccountRecharge tycoinAccountRecharge = new TycoinAccountRecharge();
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String nowDate = format.format(dateTime);

		tycoinAccountRecharge.setDateTime(dateTime);
		tycoinAccountRecharge.setPaymentTime(nowDate);
		tycoinAccountRecharge.setPaymentId(outTradeNo);
		tycoinAccountRecharge.setPayMode(6);

		String Logno = request.getParameter("Logno");
		if (!StringUtil.isNull(Logno)) {
			tycoinAccountRecharge.setLogno(Logno);
		} else {
			tycoinAccountRecharge.setLogno(RandomUtils.getRandomString(16));
		}
		String isMycharge = request.getParameter("isMycharge");
		if ("1".equals(isMycharge)) {
			tycoinAccountRecharge.setIsMycharge(1);
		} else {
			tycoinAccountRecharge.setIsMycharge(0);
		}

		if (!StringUtil.isNull(unionNotifUrl)) {
			try {
				tycoinAccountRecharge.setShopNotifUrl(URLDecoder.decode(unionNotifUrl, "UTF-8"));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		if (!StringUtil.isNull(frontUrl)) {
			try {
				frontUrl=URLDecoder.decode(frontUrl, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		tycoinAccountRecharge.setPaymentId(outTradeNo);
		tycoinAccountRecharge.setFee("0");
		tycoinAccountRecharge.setIsOnline("0");
		tycoinAccountRecharge.setMoney(txnAmt);
		tycoinAccountRecharge.setPaymentStatus(0);
		tycoinAccountRecharge.setMoneyfloat(((float) Integer.valueOf(txnAmt)) / 100);
		tycoinAccountRecharge.setUserId(userId);
		tycoinAccountRechargeService.save(tycoinAccountRecharge);

		Form_6_2_FrontConsume form_6_2_FrontConsume = new Form_6_2_FrontConsume(outTradeNo, txnAmt, frontUrl);
		try {
			form_6_2_FrontConsume.doPost(request, reponse);
		} catch (ServletException e) {
		} catch (IOException e) {
		}
	}

	@RequestMapping(value = "/findScannPayByTran", produces = "application/json;charset=UTF-8", method = RequestMethod.GET)
	@ResponseBody
	public String findScannPayByTran(HttpServletRequest request, HttpServletResponse response) {
		String orderId = request.getParameter("orderId");
		String txnTime = "";
		String resultStr = "";

		if (StringUtil.isNotNull(orderId)) {
			SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
			txnTime = format.format(new Date());
		} else {
			resultStr = "{\"code\":\"2001\",\"resultMessage\":\" orderId不能为空\"}";
			return resultStr;
		}
		Map<String, String> resultmap = new HashMap<String, String>();
		try {
			Form_6_5_Query form_6_5_Query = new Form_6_5_Query(orderId, txnTime);
			resultmap = form_6_5_Query.doPost(request, response);
			JSONObject jsonObject = JSONObject.fromObject(resultmap);

			resultStr = jsonObject.toString();
		} catch (Exception e) {
		}

		return resultStr;

	}

	@RequestMapping(value = "/RefundByTran", produces = "application/json;charset=UTF-8", method = RequestMethod.GET)
	@ResponseBody
	public String qpayRefundByTran(HttpServletRequest request, HttpServletResponse response) {
		Map<String, String> resultMap = new HashMap<String, String>();

		String orderId = request.getParameter("orderId");

		String origQryId = request.getParameter("origQryId");

		SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
		String txnTime = format.format(new Date());

		String txnAmt = request.getParameter("txnAmt");

		String resultStr = "";
		Map<String, String> resultmap = new HashMap<String, String>();
		try {
			Form_6_4_Refund form_6_4_Refund = new Form_6_4_Refund(orderId, origQryId, txnAmt, txnTime);
			resultmap = form_6_4_Refund.doPost(request, response);
			String respCode = resultMap.get("respCode");
			JSONObject jsonObject = JSONObject.fromObject(resultmap);
			resultStr = jsonObject.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return resultStr;

	}

	@RequestMapping(value = "/notiyReturn", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public void notiy_return(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println("------------我已经进入银联异步回调----------");
		/***
		 * String accessType=0 String bizType=000201 String currencyCode=156
		 * String encoding=UTF-8 String merId=826520060120023 String
		 * orderId=1499071792017102012951 String queryId=201707031649529373658
		 * String respCode=00 String respMsg=成功[0000000] String settleAmt=1
		 * String settleCurrencyCode=156 String settleDate=0703 String
		 * signMethod=01
		 * 
		 * traceNo=937365 traceTime=0703164952 txnAmt=1 txnSubType=01
		 * txnTime=20170703164952 txnType=01 version=5.1.0
		 **/

		String accessType = request.getParameter("accessType");
		String bizType = request.getParameter("bizType");
		String currencyCode = request.getParameter("currencyCode");
		String encoding = request.getParameter("encoding");
		String merId = request.getParameter("merId");
		String orderId = request.getParameter("orderId");
		String queryId = request.getParameter("queryId");
		String respCode = request.getParameter("respCode");
		String respMsg = request.getParameter("respMsg");
		String settleAmt = request.getParameter("settleAmt");
		String settleCurrencyCode = request.getParameter("settleCurrencyCode");
		String settleDate = request.getParameter("settleDate");
		String signMethod = request.getParameter("signMethod");

		String traceNo = request.getParameter("traceNo");
		String traceTime = request.getParameter("traceTime");
		String txnAmt = request.getParameter("txnAmt");
		String txnSubType = request.getParameter("txnSubType");
		String txnTime = request.getParameter("txnTime");
		String txnType = request.getParameter("txnType");
		String version = request.getParameter("version");

		LogUtil.writeLog("BackRcvResponse接收后台通知开始");

		encoding = request.getParameter(SDKConstants.param_encoding);

		// 获取银联通知服务器发送的后台通知参数

		Map<String, String> reqParam = getAllRequestParam(request);

		LogUtil.printRequestLog(reqParam);

		Map<String, String> valideData = null;

		if (null != reqParam && !reqParam.isEmpty()) {

			Iterator<Entry<String, String>> it = reqParam.entrySet().iterator();

			valideData = new HashMap<String, String>(reqParam.size());

			while (it.hasNext()) {

				Entry<String, String> e = it.next();

				String key = (String) e.getKey();

				String value = (String) e.getValue();

				value = new String(value.getBytes(encoding), encoding);

				valideData.put(key, value);

			}

		}

		// 重要！验证签名前不要修改reqParam中的键值对的内容，否则会验签不过

		if (!AcpService.validate(valideData, encoding)) {

			LogUtil.writeLog("验证签名结果[失败].");

			// 验签失败，需解决验签问题

		} else {

			LogUtil.writeLog("验证签名结果[成功].");

			// 交易成功，更新商户订单状态

			String customerInfo = valideData.get("customerInfo");

			if (null != customerInfo) {

				Map<String, String> customerInfoMap = AcpService.parseCustomerInfo(customerInfo, "UTF-8");

				LogUtil.writeLog("customerInfoMap明文: " + customerInfoMap);

			}

			TycoinAccountRecharge tycoinAccountRecharge = tycoinAccountRechargeService.findOneBypaymentId(orderId);
			String resultMessage="";
			String code="";
			if ("00".equals(respCode) && tycoinAccountRecharge != null) {
				tycoinAccountRecharge.setPaymentStatus(1);
				tycoinAccountRecharge.setShopTradeNo(queryId);
				/*tycoinAccountRecharge.setReturnText(JSONObject.fromObject(valideData).toString());*/
				tycoinAccountRechargeService.save(tycoinAccountRecharge);
 	 
				TycoinUser tycoinUser = tycoinUserService.findById(Long.valueOf(tycoinAccountRecharge.getUserId()));
				if (tycoinUser != null && StringUtil.isNotNull(String.valueOf(tycoinUser.getId()))) {
					tycoinAccountRechargeCallbackProcessService.rechargeCallbackProcess(tycoinAccountRecharge);
					code="SUCCESS";
					resultMessage="支付成功";
				}

			} else {
				tycoinAccountRecharge.setPaymentStatus(5);
				tycoinAccountRecharge.setShopTradeNo(queryId);
				tycoinAccountRechargeService.save(tycoinAccountRecharge);
				code="FAIL";
				resultMessage="支付失败";

			}			
			if(StringUtil.isNotNull(tycoinAccountRecharge.getShopNotifUrl())){
				String shopNotifUrl = tycoinAccountRecharge.getShopNotifUrl().split(",")[0];
				if (StringUtil.isNotNull(shopNotifUrl)) {
					System.out.println("开始商户异步回调shopNotifUrl=" + shopNotifUrl + "&resultMessage=" + respMsg + "&code="
							+ respCode + "&TradeNo=" + tycoinAccountRecharge.getShopTradeNo() + "&paymentId="
							+ tycoinAccountRecharge.getPaymentId());
					HttpClientUtils hct = new HttpClientUtils();
					hct.get(shopNotifUrl + "&resultMessage=" + respMsg + "&code=" + respCode + "&TradeNo="
							+ tycoinAccountRecharge.getShopTradeNo() + "&paymentId=" + tycoinAccountRecharge.getPaymentId());
				}
			}

			String accNo = valideData.get("accNo");

			// 如果配置了敏感信息加密证书，可以用以下方法解密

			if (null != accNo) {

				accNo = AcpService.decryptData(accNo, "UTF-8");

				LogUtil.writeLog("accNo明文: " + accNo);

			}

			respCode = valideData.get("respCode");

			// 判断respCode=00、A6后，对涉及资金类的交易，请再发起查询接口查询，确定交易成功后更新数据库。

		}

		LogUtil.writeLog("BackRcvResponse接收后台通知结束");

	}

	@RequestMapping(value = "/RefundNotiyReturn", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public void RefundnotiyReturn(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println("------------我已经进入银联退款异步回调----------");

		String accessType = request.getParameter("accessType");
		String bizType = request.getParameter("bizType");
		String currencyCode = request.getParameter("currencyCode");
		String encoding = request.getParameter("encoding");
		String merId = request.getParameter("merId");
		String orderId = request.getParameter("orderId");
		String queryId = request.getParameter("queryId");
		String respCode = request.getParameter("respCode");
		String respMsg = request.getParameter("respMsg");
		String settleAmt = request.getParameter("settleAmt");
		String settleCurrencyCode = request.getParameter("settleCurrencyCode");
		String settleDate = request.getParameter("settleDate");
		String signMethod = request.getParameter("signMethod");

		String traceNo = request.getParameter("traceNo");
		String traceTime = request.getParameter("traceTime");
		String txnAmt = request.getParameter("txnAmt");
		String txnSubType = request.getParameter("txnSubType");
		String txnTime = request.getParameter("txnTime");
		String txnType = request.getParameter("txnType");
		String version = request.getParameter("version");

		LogUtil.writeLog("BackRcvResponse接收后台通知开始");

		encoding = request.getParameter(SDKConstants.param_encoding);

		// 获取银联通知服务器发送的后台通知参数

		Map<String, String> reqParam = getAllRequestParam(request);

		LogUtil.printRequestLog(reqParam);

		Map<String, String> valideData = null;

		if (null != reqParam && !reqParam.isEmpty()) {

			Iterator<Entry<String, String>> it = reqParam.entrySet().iterator();

			valideData = new HashMap<String, String>(reqParam.size());

			while (it.hasNext()) {

				Entry<String, String> e = it.next();

				String key = (String) e.getKey();

				String value = (String) e.getValue();

				value = new String(value.getBytes(encoding), encoding);

				valideData.put(key, value);

			}

		}

		// 重要！验证签名前不要修改reqParam中的键值对的内容，否则会验签不过

		if (!AcpService.validate(valideData, encoding)) {

			LogUtil.writeLog("验证签名结果[失败].");

			// 验签失败，需解决验签问题

		} else {

			LogUtil.writeLog("验证签名结果[成功].");

			// 交易成功，更新商户订单状态

			orderId = valideData.get("orderId"); // 获取后台通知的数据，其他字段也可用类似方式获取

			String customerInfo = valideData.get("customerInfo");

			if (null != customerInfo) {

				Map<String, String> customerInfoMap = AcpService.parseCustomerInfo(customerInfo, "UTF-8");

				LogUtil.writeLog("customerInfoMap明文: " + customerInfoMap);

			}

			String accNo = valideData.get("accNo");

			// 如果配置了敏感信息加密证书，可以用以下方法解密

			if (null != accNo) {

				accNo = AcpService.decryptData(accNo, "UTF-8");

				LogUtil.writeLog("accNo明文: " + accNo);

			}
			TycoinAccountRecharge tycoinAccountRecharge = tycoinAccountRechargeService.findOneBypaymentId(orderId);
			String resultMessage="";
			String code="";
			if ("00".equals(respCode) && tycoinAccountRecharge != null) {
				if ("00".equals(respCode)) {					
					boolean boo = tycoinAccountRechargeCallbackProcessService
							.tycoinAccountRechargeCallBackSaveOrUpdate(tycoinAccountRecharge, request, response);
					resultMessage="退款成功";
					code="SUCCESS";
					
				}
			} else {
				tycoinAccountRecharge.setPaymentStatus(5);
				tycoinAccountRecharge.setShopTradeNo(queryId);
				tycoinAccountRechargeService.save(tycoinAccountRecharge);
				resultMessage="退款失败";
				code="ERROR";

			}
			String shopNotifUrl = tycoinAccountRecharge.getShopNotifUrl().split(",")[1];
			if (StringUtil.isNotNull(shopNotifUrl)) {
				System.out.println("开始商户异步回调shopNotifUrl=" + shopNotifUrl + "&resultMessage=" + respMsg + "&code="
						+ respCode + "&TradeNo=" + tycoinAccountRecharge.getShopTradeNo() + "&paymentId="
						+ tycoinAccountRecharge.getPaymentId() + "&refund=1");
				HttpClientUtils hct = new HttpClientUtils();
				hct.get(shopNotifUrl + "&resultMessage=" + resultMessage + "&code=" + code + "&TradeNo="
						+ tycoinAccountRecharge.getShopTradeNo() + "&paymentId=" + tycoinAccountRecharge.getPaymentId()
						+ "&refund=1");
			}

			respCode = valideData.get("respCode");

			// 判断respCode=00、A6后，对涉及资金类的交易，请再发起查询接口查询，确定交易成功后更新数据库。

		}

		LogUtil.writeLog("BackRcvResponse接收后台通知结束");
		

	}

}
